﻿#include "MapViewer.h"
#include <QScrollBar>
#include <QDebug>

MapViewer::MapViewer(QWidget *parent) : QGraphicsView(parent)
{
//    this->setStyleSheet("background-color:rgb(229, 228, 227);");
    m_isPan = false;
    m_prevPan = QPoint(0, 0);

    m_scene = new QGraphicsScene(this);
    m_scene->setBackgroundBrush(QBrush(QColor(229, 228, 227)));
    this->setScene(m_scene);

    this->setDragMode(QGraphicsView::DragMode::NoDrag);
    this->setInteractive(false);
    this->setEnabled(false);
}

void MapViewer::setQImage(const QImage &img)
{
    if(img.isNull())
        return;
    m_image = QPixmap::fromImage(img);
    initShow();
}

QImage MapViewer::getQImage()
{
    return m_image.toImage();
}

void MapViewer::setPixmap(const QPixmap &img)
{
    if(img.isNull())
        return;
    m_image = img.copy();
    initShow();
}

QPixmap MapViewer::getPixmap()
{
    return m_image;
}

void MapViewer::resetImage()
{
    if(m_image.isNull())
        return;
    m_scene->clear();
    this->setEnabled(false);
}

void MapViewer::resetSize()
{
    this->resetTransform();
    this->setSceneRect(m_image.rect());
    this->fitInView(QRect(0, 0, m_image.width(), m_image.height()), Qt::KeepAspectRatio);
}

void MapViewer::wheelEvent(QWheelEvent *event)
{
    if(m_image.isNull())
        return;

    QPoint numDegrees = event->angleDelta() / 8;
    if (!numDegrees.isNull()) {
        QPoint numSteps = numDegrees / 15;
        zoom(numSteps);
    }
    event->accept();
}

void MapViewer::keyPressEvent(QKeyEvent *event)
{
    if(event->key() == Qt::Key_W) {
        this->resetTransform();
        this->setSceneRect(m_image.rect());
        this->fitInView(QRect(0, 0, m_image.width(), m_image.height()), Qt::KeepAspectRatio);
    }
}

void MapViewer::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton){
        togglePan(true, event->pos());
        event->accept();
        return;
    }
    event->ignore();
    //    return QGraphicsView::mousePressEvent(event);
}

void MapViewer::mouseMoveEvent(QMouseEvent *event)
{
    if(m_isPan) {
        pan(event->pos());
        event->accept();
        return;
    }
    event->ignore();
    //    return QGraphicsView::mouseMoveEvent(event);
}

void MapViewer::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton){
        togglePan(false);
        event->accept();
        return;
    }
    event->ignore();
    //    return QGraphicsView::mouseReleaseEvent(event);
}

void MapViewer::zoom(QPoint factor)
{
    QRectF FOV = this->mapToScene(this->rect()).boundingRect();
    QRectF FOVImage = QRectF(FOV.left(), FOV.top(), FOV.width(), FOV.height());
    float scaleX = static_cast<float>(m_image.width()) / FOVImage.width();
    float scaleY = static_cast<float>(m_image.height()) / FOVImage.height();
    float minScale = scaleX > scaleY ? scaleY : scaleX;
    float maxScale = scaleX > scaleY ? scaleX : scaleY;
    if ((factor.y() > 0 && minScale > 100) || (factor.y() < 0 && maxScale < 1 )) {
        return;
    }
    if(factor.y()>0)
        scale(1.2, 1.2);
    else
        scale(0.8, 0.8);
}

void MapViewer::togglePan(bool pan, const QPoint &startPos)
{
    if(pan)
    {
        if(m_isPan)
            return;

        m_isPan = true;
        m_prevPan = startPos;
        setCursor(Qt::ClosedHandCursor);
    }
    else
    {
        if(!m_isPan)
            return;

        m_isPan = false;
        m_prevPan = QPoint(0,0);
        setCursor(Qt::ArrowCursor);
    }
}

void MapViewer::pan(const QPoint &panTo)
{
    QScrollBar* hBar = horizontalScrollBar();
    QScrollBar* vBar = verticalScrollBar();
    QPoint delta = panTo - m_prevPan;
    m_prevPan = panTo;
    hBar->setValue(hBar->value() - delta.x());
    vBar->setValue(vBar->value() - delta.y());
}

void MapViewer::initShow()
{
    this->setEnabled(true);
    this->setMouseTracking(true);

    m_scene->clear();
    m_scene->addPixmap(m_image);
    m_scene->update();

    this->resetTransform();
    this->setSceneRect(m_image.rect());
    this->fitInView(QRect(0, 0, m_image.width(), m_image.height()), Qt::KeepAspectRatio);
}
